﻿using AutomaticPush.Common;
using Microsoft.Extensions.Caching.Distributed;
using System.Reflection;
using System.Text;
using System.Text.Json;

namespace AutomaticPush.Extension
{
    public static class DistributedCacheExtensions
    {
        /// <summary>
        /// CachingKey 分割符
        /// </summary>
        private const string SPLIT_CHAR = ":";

        private static string _instanceName;
        private static string InstanceName
        {
            get
            {
                if (_instanceName == null)
                {
                    _instanceName = Assembly.GetEntryAssembly().GetName().Name + SPLIT_CHAR;
                }
                return _instanceName;
            }
        }

        public static void SetInstanceName(
            this IDistributedCache cache,
            string instanceName)
        {
            _instanceName = instanceName + SPLIT_CHAR;
        }

        #region Get

        public static T Get<T>(
            this IDistributedCache cache,
            string key)
        {
            var value = cache.GetString(InstanceName + key.ToLower());
            if (value == null)
                return default;
            else
                return JsonSerializer.Deserialize<T>(value, GlobalData.DefaultJsonOption);
        }

        public static async Task<T> GetAsync<T>(
            this IDistributedCache cache,
            string key,
            CancellationToken token = default)
        {
            var value = await cache.GetStringAsync(InstanceName + key.ToLower(), token);
            if (value == null)
                return default;
            else
                return JsonSerializer.Deserialize<T>(value, GlobalData.DefaultJsonOption);
        }

        public static bool TryGetValue<T>(
            this IDistributedCache cache,
            string key,
            out T outValue)
        {
            var value = cache.GetString(InstanceName + key.ToLower());
            if (value == null)
            {
                outValue = default;
                return false;
            }
            else
            {
                outValue = JsonSerializer.Deserialize<T>(value, GlobalData.DefaultJsonOption);
                return true;
            }
        }

        #endregion

        #region Set

        public static void Add<T>( this IDistributedCache cache, string key, T value,DistributedCacheEntryOptions options = null)
        {

            if (options == null)
                cache.Set(InstanceName + key.ToLower(), Encoding.UTF8.GetBytes(JsonSerializer.Serialize(value, GlobalData.DefaultJsonOption)));
            else
                cache.Set(InstanceName + key.ToLower(), Encoding.UTF8.GetBytes(JsonSerializer.Serialize(value, GlobalData.DefaultJsonOption)), options);
        }

        public static async Task AddAsync<T>(this IDistributedCache cache, string key,  T value,   DistributedCacheEntryOptions options = null, CancellationToken token = default)
        {
            if (options == null)
                await cache.SetAsync(InstanceName + key.ToLower(), Encoding.UTF8.GetBytes(JsonSerializer.Serialize(value, GlobalData.DefaultJsonOption)), token);
            else
                await cache.SetAsync(InstanceName + key.ToLower(), Encoding.UTF8.GetBytes(JsonSerializer.Serialize(value, GlobalData.DefaultJsonOption)), options, token);
        }

        #endregion


        #region Delete

        public static void Delete(
            this IDistributedCache cache,
            string key)
        {
            cache.Remove(InstanceName + key.ToLower());
        }

        public static async Task DeleteAsync(
            this IDistributedCache cache,
            string key,
            CancellationToken token = default)
        {
            await cache.RemoveAsync(InstanceName + key.ToLower(), token);
        }

        #endregion
    }
}
